# -*-coding:utf-8 -*-


from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from .models import Book, Publish


class PublishSerializer(serializers.ModelSerializer):
    """publish序列化"""

    class Meta:
        model = Publish
        fields = ('id', 'name', 'addres')


# 100 多表序列化 3种方式
# 方式1：不推荐
# 方式2：子序列化
# 方式3：在model直接定义方法属性
class BookSerializer(serializers.ModelSerializer):
    # 方式1：了解：该方式设置的序列化字段必须在fields中声明
    # 不推荐（推荐在model直接定义方法属性）
    publish_address = serializers.SerializerMethodField()

    def get_publish_address(self, instance):
        return instance.publish.addres

    # 方式2：
    # 自定义表深度-子序列化方式
    publish = PublishSerializer()

    class Meta:
        # 序列化关联的model类
        model = Book

        # 可插拔式
        # 参与序列化的字段
        fields = ('id', 'name', 'price', 'img',
                  'fn', 'publish_name', 'author_list',  # 推荐：自定义model方法属性
                  'publish_address',  # 不推荐了
                  'publish',  # 推荐：子序列化方法
                  )

        # ZZZ 了解知识（不重要
        # 全部字段
        # fields = '__all__'
        # 与filed不共存，exclude排斥某些字段
        # exclude = ('id', 'is_deleted')
        # 自动连表深度 拓展性太差
        # depth = 1


# 200 多表反序列化
# ModelSerializer自带create和update方法
class BookDModelSerializer(serializers.ModelSerializer):
    # serializers.SerializerMethodField(error_messages=)  # 如何找到error_messge
    class Meta:
        model = Book
        fields = ('name', 'price', 'publish', 'authors')
        # extra_kwargs 用来完成反序列字段的，系统校验规则
        # 相当于之前在前面定义的每个字段
        extra_kwargs = {
            'name': {
                'required': True,
                'min_length': 3,
                'error_messages': {
                    'required': 'name为必填项',
                    'min_length': 'name为不能少于3个字符'
                }
            }
        }

    # 局部钩子
    def validate_name(self, value):
        if 'g' in value.lower():
            raise serializers.ValidationError('g不能包含在name中')
        return value

    # 全局钩子
    def validate(self, attrs):
        publish = attrs.get('publish')  # 外键变成了对象
        name = attrs.get('name')
        print(type(publish))
        if Book.objects.filter(name=name, publish=publish):
            raise ValidationError('该书已存在')

        return attrs

    # ModelSerializer 已经帮我们实现了 create与update方法
    # 我们使用的重点就是钩子


# 300 序列化和反序列化整合
"""
1) fields中设置所有序列化与反序列化字段
2) extra_kwargs划分只序列化or反序列化字段
    write_only:只反序列化
    read_only:只序列化
    自定义默认字段只序列化(read_only)
    如果字段没设置write_only或者read_only，那么该字段可以序列化和反序列化
3) 设置反序列化所需的系统校验、局部钩子、全局钩子
"""
from rest_framework.serializers import ListSerializer


# 400 群改
# 重点：ListSerializer与ModelSerializer监理关联的是：
# ModelSerializer中的
# class Meta:
#       list_serializer_class = V2BookListSerializer

class V2BookListSerializer(ListSerializer):
    def update(self, instance, validated_data):
        print(instance)  # 要更新的对象们:[obj1,obj2,...]
        print(validated_data)  # 要更新的对象对应的数据们:[{},{},{}]
        print(self.child)  # 服务的模型序列化类-V2BookModelSerializer

        # ListSerializer中create的代码
        # return [self.child.create(attrs) for attrs in validated_data

        for index, obj in enumerate(instance):
            self.child.update(obj, validated_data[index])
        return instance


class V2BookModelSerializer(serializers.ModelSerializer):
    # 100 序列化字段 （了解下）
    # publish_address = serializers.SerializerMethodField()
    #
    # def get_publish_address(self, instance):
    #     return instance.publish.addres

    # ERROR 100 子序列化字段  （了解下）
    # ERROR publish和反序列化的 publish:1 冲突
    # publish为book表自带的外键id字段
    # 解决办法？ get post不同的方式，调用不同的publish
    # publish = PublishSerializer()

    class Meta:
        # 序列化 反序列化
        model = Book  # 关联的model类

        # 300 参与序列化、反序列化的字段
        fields = ('id', 'name', 'price', 'img', 'fn', 'author_list', 'publish_name',
                  'publish', 'authors',
                  )

        # 300 序列化、反序列化的系统校验规则 (重点！！！)
        extra_kwargs = {

            # 200 反序列化字段
            'name': {
                'required': True,
                'min_length': 3,
                'error_messages': {
                    'required': 'name为必填项',
                    'min_length': 'name为不能少于3个字符'
                }
            },
            'publish': {'write_only': True},  # 200 反序列化字段
            'authors': {'write_only': True},  # 200 反序列化字段
            'img': {'read_only': True},  # 100 序列化字段
            'author_list': {'read_only': True},  # 100 序列化字段
            'publish_name': {'read_only': True}  # 100 序列化字段
        }

        # 400 群改，需要设置自定义ListSerializer,重写群改的update方法
        list_serializer_class = V2BookListSerializer

    # 200 反序列化字段，局部钩子
    def validate_name(self, value):
        if 'g' in value.lower():
            raise serializers.ValidationError('g不能包含在name中')
        return value

    # 200 反序列化字段，全局钩子
    def validate(self, attrs):
        # 访问view视图类传递过来的参数
        # 从view传递进来的context={'request': request}
        request = self.context.get('request')
        print(request.method)  # PATCH
        print(request.user)  # AnonymousUser

        publish = attrs.get('publish')  # 外键变成了对象
        name = attrs.get('name')
        print(11111111111)
        print(type(publish))
        if Book.objects.filter(name=name, publish=publish):
            raise ValidationError('该书已存在')
        return attrs
